package com.ck.util;

import org.apache.commons.lang3.StringUtils;
import org.bytedeco.javacpp.opencv_core;
import org.bytedeco.javacpp.opencv_core.IplImage;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.FrameGrabber.Exception;
import org.bytedeco.javacv.Java2DFrameConverter;
import org.bytedeco.javacv.OpenCVFrameConverter;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

/**
 * 视频工具类
 *
 * @author linqiang
 * @date 2018-07-11 14:31
 */
public class VideoUtils {

    public static final String IMG_TYPE_JPG = "jpg";
    public static final String IMG_TYPE_PNG = "png";

    /**
     * 随机从视频中采集一张图片保存到指定路径
     * 支持视频类型： mov,mp4,m4a,3gp,3g2,mj2
     *
     * @param videoPath      视频源地址, 如：D:\\test.MP4
     * @param targetFilePath 图片保存地址, 如D:\\img
     * @param targetFileName 图片保存名称, 如：aaa
     * @param imageType      图片类型（jpg, gif, png, jpeg）,默认jpg
     * @return 图片保存路径，如: D:\\img\aaa.jpg
     * @throws Exception
     */
    public static String randomGrabberImage(String videoPath, String targetFilePath, String targetFileName, String imageType)
            throws Exception {
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath);
        ff.start();
        String rotate = ff.getVideoMetadata("rotate");
        Frame f = ff.grabImage();
        if (null != rotate && rotate.length() > 1) {
            OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
            IplImage src = converter.convert(f);
            f = converter.convert(rotate(src, Integer.valueOf(rotate)));
        }
        String fileUrl = doExecuteFrame(f, targetFilePath, targetFileName, imageType);
        ff.stop();
        return fileUrl;
    }


    /**
     * 随机从视频中采集一张图片保存到指定路径
     * 支持视频类型： mov,mp4,m4a,3gp,3g2,mj2
     *
     * @param videoPath      视频源地址, 如：D:\\test.MP4
     * @param targetFilePath 图片保存地址, 如D:\\img
     * @param targetFileName 图片保存名称, 如：aaa
     * @param imageType      图片类型（jpg, gif, png, jpeg）,默认jpg
     * @return 图片文件
     * @throws Exception
     */
    public static File randomGrabberImageReturnFile(String videoPath, String targetFilePath, String targetFileName, String imageType)
            throws Exception {
        FFmpegFrameGrabber ff = FFmpegFrameGrabber.createDefault(videoPath);
        ff.start();
        String rotate = ff.getVideoMetadata("rotate");
        Frame f = ff.grabImage();
        if (null != rotate && rotate.length() > 1) {
            OpenCVFrameConverter.ToIplImage converter = new OpenCVFrameConverter.ToIplImage();
            IplImage src = converter.convert(f);
            f = converter.convert(rotate(src, Integer.valueOf(rotate)));
        }
        File file = doExecuteFrameReturnFile(f, targetFilePath, targetFileName, imageType);
        ff.stop();
        return file;
    }

    /**
     * 选择角度
     *
     * @param src   视频资源
     * @param angle 角度
     * @return
     */
    public static IplImage rotate(IplImage src, int angle) {
        IplImage img = IplImage.create(src.height(), src.width(), src.depth(), src.nChannels());
        opencv_core.cvTranspose(src, img);
        opencv_core.cvFlip(img, img, angle);
        return img;
    }

    /**
     * 写图片
     *
     * @param f              图片源
     * @param targetFilePath 图片保存地址
     * @param targetFileName 图片名称
     * @param imageType      图片类型（jpg, gif, png, jpeg）
     */
    private static String doExecuteFrame(Frame f, String targetFilePath, String targetFileName, String imageType) {
        if (null == f || null == f.image) {
            return "";
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        if (StringUtils.isBlank(imageType)) {
            imageType = IMG_TYPE_JPG;
        }
        String fileUrl = targetFilePath + File.separator + targetFileName + "." + imageType;
        BufferedImage bi = converter.getBufferedImage(f);
        File output = new File(fileUrl);
        try {
            ImageIO.write(bi, imageType, output);
            return fileUrl;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return "";
    }


    /**
     * 写图片
     *
     * @param f              图片源
     * @param targetFilePath 图片保存地址
     * @param targetFileName 图片名称
     * @param imageType      图片类型（jpg, gif, png, jpeg）
     */
    private static File doExecuteFrameReturnFile(Frame f, String targetFilePath, String targetFileName, String imageType) {
        if (null == f || null == f.image) {
            return null;
        }
        if (StringUtils.isBlank(imageType)) {
            imageType = IMG_TYPE_JPG;
        }
        Java2DFrameConverter converter = new Java2DFrameConverter();
        String fileUrl = targetFilePath + File.separator + targetFileName + "." + imageType;
        BufferedImage bi = converter.getBufferedImage(f);
        File output = new File(fileUrl);
        try {
            ImageIO.write(bi, imageType, output);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return output;
    }

    public static void main(String[] args) throws Exception {
        randomGrabberImage("D:\\迷你红.mp4", "D:\\", "迷你红", null);
    }
}